1 PARTE I – Cuidados antes de começar a rodar os códigos no R

Pensar quais orientações são mais gerais e quais são importantes de acompanhar cada código.

1.1 Rstudio/Pacotes/versões/sistemas operacionais

Sobre os pacotes, seria bom ter uma listinha de ‘library’ no início de cada código? Talvez com uma breve explicação do que cada pacote faz, versão mínima… não sei.

OBS: essa tabela é uma referência para obtermos as versões dos pacotes ao final do desenvolvimento do script. Ela está automatizada, então quando terminarmos ele precisamos refaze-lo de forma que não gere mais mudança nas versões (tem que fazer a tabela na mão mesmo…).

Tabela xx - configuração de pacotes necessários e respectivas versões mínimas que devem ser utilizadas para reproduzir os códigos

Pacotes

Versão

R

R version 4.2.3 (2023-03-15)

dplyr

1.1.1

Distance

1.0.7

DT

0.27

flextable

0.9.1

ggplot2

3.4.1

plotly

4.10.1

readr

2.1.4

readxl

1.4.2

tibble

3.2.1

tidyr

1.3.0

1.2 Cuidados com a planilha .xlsx que será importada (para que mantenha o padrão da planilha de referência do ICMBio)

Algumas funções foram escritas para funcionar tomando como base de dados de referência a planilha em formato excel Planilha Oficial consolidada de Masto-aves 2014-21 Validada CEMAVE CPB CENAP.xlsx disponibilizada pelo Projeto Monitora. Estas funções carregam os dados e fazem uma série de transformações para devolve-los no formato padronizado do programa DISTANCE para Windows. Portanto, para garantir a reprodutibilidade dos códigos produzidos em versões atualizadas da base de dados do Monitora, é importante tomar alguns cuidados.

O primeiro e mais importante cuidado é manter os mesmos nomes das colunas em versões atualizadas da base de dados do Monitora. As primeiras funções, além de carregar os dados, aplicam uma série de transformações. Os nomes das colunas são alterados, e a essas são atribuídos tipos (data, caracter, fator , inteiro e numérico), linhas são eliminadas e novas colunas são gereadas. Para exemplificar, veja o código abaixo. Ele foi escrito para executar as primeiras transformações nos dados e constitui o corpo da função carregar_dados_filtrados().

O trecho do código que vai da linha 101 a 113 serve selecionar apenas as colunas de interesse presente nos dados originais. Note que os nomes das planilhas originais constam nesse trecho. Caso o nome de qualque uma dessas colunas seja alterado a função deixará de funcionar.

Outro aspecto importante é a presença de observações não preenchidas (ex. células vazias) nos dados originais. A função foi desenha para resolver alguns problemas presentes nos dados originais. Por exemplo, nas o trecho do código das linhas xx a xx as observações vazias (NAs) são substituidas pelo valor correto na coluna day_effort. Essa correção continnuará sendo realizada em versões atualizadas dos dados do Monitora. Porém, se outras colunas além das que estão sendo corrigidas possuirem observações vazias os dados serão carregados e transformados, porém outras funções podem ter o seu funcionamento comprometido. Por exemplo… (funções de visualização e do pacote distance que podem naõ funcionar devido a ausência de observação)

Dentre todas as funções de carregamento de dados, apenas carregar_dados_brutos() carrega a base de dados originais do Monitora, diretamente do diretório data-raw/monitora_masto_aves_2023_04_04.xlsx. Ao mesmo tempo que carrega e transforma os dados, essa função gera uma versão em um formato mais leve, .rds, no diretório data-raw (data-raw/monitora_masto_aves_2023_04_04.rds). A função seguinte no fluxo de trabalho carrega a base a partir dessa versão mais leve. Logo, sempre que houver atualizações no arquivo original de dados brutos é necessário iniciar a rotina de carregamento de dados necessariamente com a função carregar_dados_brutos().

Outros cuidados…

Imaginando que a planilha de dados do monitora é algo dinâmico, que o nome das colunas pode ser editado…

1.3 Como abrir os arquivos: como salvar e descompactar a pasta. Abrir projeto

Um passo a passo de como salvar arquivo com os códigos e abrir.. Por exemplo, da forma como está é interessante descompactar a pasta e acessar os arquivos abrindo o projeto. Acho que isso pode mudar, dependendo de como viermos a entregar o produto final. Então podemos pensar nessa explicação no final.

1.4 Cuidados com diretório

Se a gente ainda precisar ter algum tipo de preocupação quanto a isso. Acho que não. Explicar a estrtura de diretórios do projeto.

1.5 Como rodar cada tipo de arquivo (markdown, shiny)

Não é trivial para quem não está acostumado… usar runApp, knit… até mesmo o shift+enter para rodar as linhas de comando uma a uma

2 PARTE II – Carregando os dados para o R

2.1 Dados brutos

Não precisa se assustar com a infnidade de códigos no exemplo acima. Serviu apenas para ilustrar que construir essas funções facilita a execução e a reprodutibilidade das análise dos dados do Monitora. Para cada tarefa existe uma função cujo funcionamento não necessita de preenchimento dos argumentos (embora seja possível fornece-los). Por traz das cortinas, as funções executam as tarafas necessárias para se obter o resultado desejado. Por exemplo, o mesmo resultado pode ser obtido utilizando apenas duas funções: carregar_dados_brutos_xlsx()e gerar_tabdin_dados_brutos().

A função gerar_tabdin_dados_brutos(), por configuração, gera uma tabela dinâmica com 1000 linhas. Você pode controlar o número de linhas pelo argumento n_linhas =. Mas atenção! Ela não funcionará com um número superior a 4.500 linhas. Ao mudar a entrada de dados usando o argumento dados =, certifique-se de que seu número de linhas não exceda esse limite (ex. 4.500). INSERIR NOTA (após testar em máquinas diferentes) Esse valor pode varia de acordo com as configurações da sua máquina.

2.2 Dados completos

  • todas espécies/UCs – carrega_dados_1.Rmd Descrever o que os dados trazem e porque foram formatados dessa forma.
# carregar dados para o R
dados_completos <- carregar_dados_completos() 
dados_completos

tabela dinamica

# gerar tabela dinamica dos dados completos
gerar_tabdin_dados_completos()

2.3 Dados filtrados

  • por espécie/UC – carrega_dados_2.Rmd até o momento usado com o exemplo da cutia na Resex Tapajós-Arapiuns Descrever o que os dados trazem e porque foram formatados dessa forma.
# carregar dados para o R
dados_filtrados <- carregar_dados_filtrados()
dados_filtrados
# gerar tabela dinâmica
gerar_tabdin_dados_filtrados()

3 Parte III – Transformando dados para Distance

3.1 Dados completos

  • todas espécies/UCs – transformar_para_distanceR.Rmd
# transformar os dados para o formato do Distance
dados_distanceR_completo <- transformar_para_distanceR()
dados_distanceR_completo

Em princípio tudo certo até aqui.

# transformar os dados para o formato do Distance
dados_distance_r_covariaveis <- transformar_para_distanceR_covariaveis()
dados_distance_r_covariaveis
# tabdin de dados_distanceR_covariaveis
gerar_tabdin_dados_distanceR_completo_cov()

4 PARTE IV – Explorando e selecionando os dados para as análises

4.1 Selecionando os melhores modelos de estudo de acordo com os dados

Critŕios:

  • espécies com maior volume de dados total
  • maior volume de dados por UC – exploração_01.nb.html (acho que o .Rmd para gerar esse html não está na pasta Monitora). Eu tinha gostado bastante desse documento, com as tabelas dinâmicas. Talvez dê para selecionar as perguntas que são válidas de deixar/ tirar/ incluir. WWF - Projeto Monitora
  • espécies validadas

4.1.1 Exploração e seleção de dados

4.1.1.1 Aspectos relacionados ao número total de observações

Sistematizar os critérios utilizados para eliminar observações (linhas).

Pensar num esquema de árvore de decisão para se chegar ao subconjunto de dados que será analisados.

4.1.1.2 Quantas observações foram validadas para quais níveis taxonômicos?

Essas operações são realizadas sobre a tabela de dados dados_completos pois os dados que foram transformados para o formato do distace no R não possuem a coluna validation, necessária para essas opereações. Mais a frente o procedimento de como obter os dados selecionados e transformatos para o formato das análises será demonstrado.

# contar observações validadas ao nível de espécie
n_obs_validadas <- contar_n_obs_validadas()
n_obs_validadas
[1] 20790   318  6550    14   215

Foram selecionadas apenas as observações validadas ao nível de espécie, somando um total 20790 observações.

# gerar gráfico com número observações validadas para cada nível taxonômico
plotar_n_obs_validadas()

Filnalmente chegamos ao subconjunto dos dados que será utilizado para selecionar quais espécies serão analisadas.

4.1.1.3 Quantas unidades de conservação ao todo?

# contar número total de UC's 
n_ucs <- contar_n_uc()
n_ucs
[1] 40

Os dados são provenientes de 40 unidades de conservação ao todo.

4.1.1.4 Quantas espécies ao todo?

n_sp <- contar_n_sp()
n_sp
[1] 209

Até aqui temos dados para 209 espécies.

4.1.1.5 Quantas observações por unidade de conservação ao todo?

As UC’s foram filtradas de acordo com o número de observações permitir a visualização.

A função de contagem de UC’s gerou 40 UC’s, mas só há observações para 38. Lembrar de verificar isso.

# contar número de observações por UC
n_obs_uc <- contar_n_obs_uc()
n_obs_uc

Adicionar o nome completo da UC na caixa interativa do gráfico. Identificar os plotes com subtítulos ex tentar adicionar título aos plotes Adicionar nomes das UCs nos 3 primeiros gáficos (descompartilhar eixo x)

# plotar o número de observações por UC
plotar_n_obs_uc_interativo()
# gerar tabdin
gerar_tabdin_n_obs_uc()

4.1.1.6 Quantas observações para cada espécie?

Número de observações por espécie.

# contar total sp
n_obs_sp <- contar_n_obs_sp()
n_obs_sp

Esse gráfico pode melhorar. Descompartilhar o eixo x? Abreviar o nome das espécies…

Tabela interativa para consulta do número de observações por espécie.

4.1.1.7 Quais e quantas observações para cada espécie por unidades de conservação?

Gerar função para plotar o número de observações para cada espécie por UC.

# gerar tabela com o número de observações por espécie e por UC
n_obs_sp_uc <- contar_n_obs_sp_uc()
n_obs_sp_uc

Gerar função tabela dinâmica.

4.1.1.8 Quantas unidades de conservação foram amostradas em cada ano?

Gerar função para visualizar número de UCs amostradas em cada ano.

Gerar função para tabela dinâmica.

4.1.1.9 Quais unidades de conservação foram amostradas em um maior número de anos?

Gerar gráfico com o número de anos em que cada UC foi amostrada.

Tabela

n_ano_uc <- contar_n_ano_uc()
`summarise()` has grouped output by 'uc_name'. You can override using the `.groups` argument.
n_ano_uc  

Gerar tabela dinamica.

4.1.1.10 Quantas observações foram realizadas por UC em cada ano?

Tabela interativa para consultar quantas observações foram realizadas por ano em cada UC

dados1 |>  
  dplyr::count(ano, ucs) |> 
  DT::datatable(filter = list(position = "top"))

4.1.1.11 Quantas observações para cada espécies por ano?

Tabela interativa para consultar quantas observações foram realizadas para cada espécie em cada ano

dados1 |>  
  dplyr::count(ano, especie) |> 
  DT::datatable(filter = list(position = "top"))

4.1.1.12 Quantas observações para cada espécies por UC e por ano?

Tabela interativa para consultar quantas observações foram realizadas para cada espécie em cada ano

dados1 |>  
  dplyr::count(ano, ucs, especie) |> 
  DT::datatable(filter = list(position = "top"))

4.1.1.13 Quantas observações para cada espécies por UC, por estação e por ano?

dados1 |>  
  dplyr::count(ano, season, uc_name, sp) |> 
  DT::datatable(filter = list(position = "top"))

4.1.1.14 Selecionando melhores modelos de estudo considerando estratificação espacial/temporal – se há suficiência amostral (60-80 observações) por estrato

  • Possíveis estratificações espaciais – EAs/UCs

                      - UCs/Espécies
    • Possíveis estratificações temporais – Espécie/UC/Ano

4.1.1.15 Avaliando distância de truncamento

  • Gráficos de distribuição das frequências de ocorrência x distância perpendicular. Arquivos gráfico-exploratorio1.Rmd e gráfico-exploratorio2.Rmd (eu não sei como você fez para incluir aquela linha vermelha com o valor de w no gráfico exploratório 2, mas ficou legal)

4.1.1.16 Distribuição de distâncias

# carregar dados_filtrados.R da pasta data para o R
dados_filtrados <- readr::read_rds(corrigir_diretorio(corrige = "data/dados_filtrados.rds")) 

# gerar o gráfico exploratório da distribuição de distâncias perpendiculares para a espécies Dasyrocta croconota na Resex Tapajós-Arapiuns
fig <- dados_filtrados |>
  # excluir NA's da variável distance
  tidyr::drop_na(distance) |> 
  grafico_exploratorio3()

fig

4.1.1.17 Avaliando covariáveis

– As covariáveis devem ser pensadas de acordo com o grupo taxonômico. Espécies que formam grupos devem ter a covariável ‘size’.

As estratégias de estratificação podem ser substituídas por covariáveis também (estratos espaciais/ ano)

Como covariável temporal, pode se pensar em usar, além do ano, a estação do ano (season), o horário do dia (para animais que variam a atividade). O horário do dia pode ser convertido em tempo após nascer do sol (como no exemplo). Mas para isso é necessário criar essa variável no dataset. E não é trivial porque precisa saber o horário de nascer do sol em cada dia/local para calcular.

ATENÇÃO: gerar gráficos distância x covariável

Exemplo de Gráficos de Marques et al. 2007

5 PARTE V – Ajustando os modelos

Esse trabalho do Marque et al. 2007 é uma boa referência de como usar as abordagens CDS global, CDS estratificada e MCDS.

Aqui, é possível testar alguns caminhos de modelos. A estratificação só faz sentido quando o volume de dados for grande. Ainda assim o uso de covariáveis pode substituir a estratificação. Pensar em como orientar o uso dessas abordagens

5.1 Modelos pela abordagem CDS – dados globais

  • função ds do Distance (argumentos básicos: truncation; key, adjustment, scale… estudar argumentos para ver se mais algum interessa)

5.2 Modelos pela abordagem CDS – dados estratificados

  • Aqui precisa ver direitinho os cuidados que precisa ter para ajustar as funções nos dados estratificados. Acho que faz em blocos. Vai aplicando os mesmos parâmetros para todos os estratos a cada modelo.

  • para cada estrato (espacial ou temporal) usar - função ds do Distance (argumentos básicos: truncation; key, adjustment, scale… estudar argumentos para ver se mais algum interessa)

5.3 Modelos pela abordagem MCDS – dados globais

Aqui não faz sentido estratificar

  • função ds do Distance (argumentos básicos: truncation; key, adjustment, scale… estudar argumentos para ver se mais algum interessa… para as covariáveis entra o argumento formula)

Dicas em Miller et al. 2019 sobre covariáveis (ver arquivo no driver).

6 PARTE VI – Avaliando os modelos

6.1 Ajuste dos modelos

  • função gof_ds

– para gerar Q-Q plots e testes associados

6.2 Selecionando modelos (AIC)

– função summarize_ds_models

DICAS EXTRAS DE MILLER et al. 2019

7 PARTE VII – PRODUTO FINAL

Criar expressões reativas

reactive() eventReactive()

observe() observeEvent()

reactiveVal() reactiveValues()

isolate()

8 Glossário

Descrever as variáveis (colunas), termos técnicos ao longo do texto…

LS0tCnRpdGxlOiAiRXNib8OnbyBkbyBmbHV4byBkZSB0cmFiYWxobyBkZSBwcm9kdcOnw6NvIGRvcyBjw7NkaWdvcyIKZGF0ZTogIkNyaWFkbyBlbSAzMSBkZSBtYXLDp28gZGUgMjAyMywgYXR1YWxpemFkbyBlbSBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkIGRlICVCIGRlICVZJylgIgphdXRob3I6IAotIEx1Y2lhbmEgRnVzaW5hdHRvCi0gVml0b3IgQm9yZ2VzLUrDum5pb3IKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDUKICAgIHRvY19mbG9hdDogZmFsc2UKICAgIG51bWJlcl9zZWN0aW9uOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKLS0tCgpgYGB7ciBjb25maWd1cmHDp8OjbywgaW5jbHVkZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBjYXJyZWdhciBwYWNvdGVzIG5lY2Vzc8OhcmlvcwojIGNhcnJlZ2FyIHBhY290ZXMgcGFyYSBjYXJyZWdhciBkYWRvcwpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHJlYWR4bCkKCiMgY2FycmVnYXIgcGFjb3RlcyBwYXJhIG1hbmlwdWxhw6fDo28gZG9zIGRhZG9zCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkodGlkeXIpCgojIGNhcnJlZ2FyIHBhY290ZXMgcGFyYSBnZXJhciB0YWJlbGFzIGRlIGRhZG9zCmxpYnJhcnkoRFQpCmxpYnJhcnkoZmxleHRhYmxlKQpsaWJyYXJ5KHRpYmJsZSkKCiMgY2FycmVnYXIgcGFjb3RlcyBwYXJhIHZpc3VhbGl6YcOnw6NvIGRvcyBkYWRvcwpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGxvdGx5KQoKIyBjYXJyZWdhciBwYWNvdGVzIHBhcmFyIGFuw6FsaXNlIGRlIGRhZG9zCmxpYnJhcnkoRGlzdGFuY2UpCgojIGNhcnJlZ2FyIGFzIGZ1bsOnw7VlcyBkYSBwYXN0YSBSCiMgY2FycmVnYXIgZnVuw6fDo28gY29ycmlnaXJfZGlyZXRvcmlvLlIKc291cmNlKAogIHBhc3RlMCgKICAgIHN0cmluZ3I6OnN0cl9yZW1vdmUoCiAgICAgIGdldHdkKCksIAogICAgICAnZG9jJwogICAgKSwKICAgICJSL2NvcnJpZ2lyX2RpcmV0b3Jpby5SIgogICkKKSAKCiMgY2FycmVnYXIgZnVuw6fDo28gY2FycmVnYXJfZGFkb3NfYnJ1dG9zX3hsc3guUgpzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJSL2NhcnJlZ2FyX2RhZG9zX2JydXRvc194bHN4LlIiCiAgKQopCgojIGNhcnJlZ2FyIGZ1bsOnw6NvIGdlcmFyX3RhYmRpbl9kYWRvc19icnV0b3MKc291cmNlKAogIGNvcnJpZ2lyX2RpcmV0b3JpbygKICAgIGNvcnJpZ2UgPSAiUi9nZXJhcl90YWJkaW5fZGFkb3NfYnJ1dG9zLlIiCiAgKQopCgojIGNhcnJlZ2FyIGEgZnVuw6fDo28gY2FycmVnYXJfZGFkb3NfY29tcGxldG9zCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgY29ycmlnZSA9ICdSL2NhcnJlZ2FyX2RhZG9zX2NvbXBsZXRvcy5SJwogICkKKQoKIyBjYXJyZWdhciBmdW7Dp8OjbyBnZXJhcl90YWJkaW5fZGFkb3NfY29tcGxldG9zCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gIlIvZ2VyYXJfdGFiZGluX2RhZG9zX2NvbXBsZXRvcy5SIgogICkKKQoKIyBjYXJyZWdhciBhIGZ1bsOnw6NvIGNhcnJlZ2FyIGRhZG9zIGZpbHRyYWRvcwpzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgIGNvcnJpZ2UgPSAnUi9jYXJyZWdhcl9kYWRvc19maWx0cmFkb3MuUicKICApCikKCiMgY2FycmVnYXIgYSBmdW7Dp8OjbyBnZXJhcl90YWJkaW5fZGFkb3NfZmlsdHJhZG9zCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gJ1IvZ2VyYXJfdGFiZGluX2RhZG9zX2ZpbHRyYWRvcy5SJwogICkKKQoKIyBjYXJyZWdhciBmdW7Dp8OjbyB0cmFuc2Zvcm1hcl9wYXJhX2Rpc3RhbmNlUgpzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICIvUi90cmFuc2Zvcm1hcl9wYXJhX2Rpc3RhbmNlUi5SIgogICkKKQoKIyBjYXJyZWdhciBhIGZ1bsOnw6NvIGdlcmFyX3RhYmRpbl9kYWRvc19kaXN0YW5jZVJfY29tcGxldG8Kc291cmNlKAogIGNvcnJpZ2lyX2RpcmV0b3JpbygKICAgIGNvcnJpZ2UgPSAnL1IvZ2VyYXJfdGFiZGluX2RhZG9zX2Rpc3RhbmNlUl9jb21wbGV0by5SJwogICkKKQoKIyBjYXJyZWdhciBhIGZ1bsOnw6NvIGdlcmFyX3RhYmRpbl9kYWRvc19kaXN0YW5jZVJfY29tcGxldG8Kc291cmNlKAogIGNvcnJpZ2lyX2RpcmV0b3JpbygKICAgIGNvcnJpZ2UgPSAnL1IvdHJhbnNmb3JtYXJfcGFyYV9kaXN0YW5jZVJfY292YXJpYXZlaXMuUicKICApCikKCiMgY2FycmVnYXIgYSBmdW7Dp8OjbyBnZXJhcl90YWJkaW5fZGFkb3NfZGlzdGFuY2VSX2NvbXBsZXRvCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gJy9SL2dlcmFyX3RhYmRpbl9kYWRvc19kaXN0YW5jZVJfY29tcGxldG9fY292LlInCiAgKQopCgojIGNhcnJlZ2FyIGZ1bsOnw6NvIGNhcnJlZ2FyX2RhZG9zX2V4cGxvcmFjYW8uUgpzb3VyY2UoCiAgY29ycmlnaXJfZGlyZXRvcmlvKAogICAgY29ycmlnZSA9ICJSL2NhcnJlZ2FyX2RhZG9zX2V4cGxvcmFjYW8uUiIKICApCikgCgojIGNhcnJlZ2FyIGZ1bsOnw6NvIGdyYWZpY29fZXhwxLpvcmF0b3Jpb19pbnRlcmF0aXZvCnNvdXJjZSgKICBjb3JyaWdpcl9kaXJldG9yaW8oCiAgICBjb3JyaWdlID0gIlIvZ3JhZmljb19leHBsb3JhdG9yaW9faW50ZXJhdGl2by5SIgogICkKKSAKCgpgYGAKCiMgKipQQVJURSBJIOKAkyBDdWlkYWRvcyBhbnRlcyBkZSBjb21lw6dhciBhIHJvZGFyIG9zIGPDs2RpZ29zIG5vIFIqKgoKUGVuc2FyIHF1YWlzIG9yaWVudGHDp8O1ZXMgc8OjbyBtYWlzIGdlcmFpcyBlIHF1YWlzIHPDo28gaW1wb3J0YW50ZXMgZGUgYWNvbXBhbmhhciBjYWRhIGPDs2RpZ28uCgojIyAqKlJzdHVkaW8vUGFjb3Rlcy92ZXJzw7Vlcy9zaXN0ZW1hcyBvcGVyYWNpb25haXMqKgoKU29icmUgb3MgcGFjb3Rlcywgc2VyaWEgYm9tIHRlciB1bWEgbGlzdGluaGEgZGUg4oCYbGlicmFyeeKAmSBubyBpbsOtY2lvIGRlIGNhZGEgY8OzZGlnbz8KVGFsdmV6IGNvbSB1bWEgYnJldmUgZXhwbGljYcOnw6NvIGRvIHF1ZSBjYWRhIHBhY290ZSBmYXosIHZlcnPDo28gbcOtbmltYS4uLiBuw6NvIHNlaS4KCioqT0JTKio6IGVzc2EgdGFiZWxhIMOpIHVtYSByZWZlcsOqbmNpYSBwYXJhIG9idGVybW9zIGFzIHZlcnPDtWVzIGRvcyBwYWNvdGVzIGFvIGZpbmFsIGRvIGRlc2Vudm9sdmltZW50byBkbyBzY3JpcHQuIEVsYSBlc3TDoSBhdXRvbWF0aXphZGEsIGVudMOjbyBxdWFuZG8gdGVybWluYXJtb3MgZWxlIHByZWNpc2Ftb3MgcmVmYXplLWxvIGRlIGZvcm1hIHF1ZSBuw6NvIGdlcmUgbWFpcyBtdWRhbsOnYSBuYXMgdmVyc8O1ZXMgKHRlbSBxdWUgZmF6ZXIgYSB0YWJlbGEgbmEgbcOjbyBtZXNtby4uLikuCgpgYGB7cn0KIyBnZXJhciBpbmZvcm1hw6fDtWVzIHNvYnJlIG9zIHBhY290ZXMgY2FycmVnYWRvcwppbmZvIDwtIHNlc3Npb25JbmZvKCkKCiMgZ2VyYXIgdGFiZWxhIGNvbSBvcyBwYWNvdGVzIGUgdmVyc8O1ZXMKdGliYmxlOjp0cmliYmxlKAogIH5QYWNvdGVzLCAgICAgICAgICAgICAgICAgICAgICAgICB+VmVyc8OjbywKICB2ZXJzaW9uJGxhbmd1YWdlLCAgICAgICAgICAgICAgICAgdmVyc2lvbiR2ZXJzaW9uLnN0cmluZywKICBpbmZvJG90aGVyUGtncyRkcGx5ciRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkZHBseXIkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyREaXN0YW5jZSRQYWNrYWdlLCAgaW5mbyRvdGhlclBrZ3MkRGlzdGFuY2UkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyREVCRQYWNrYWdlLCAgICAgICAgaW5mbyRvdGhlclBrZ3MkRFQkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyRmbGV4dGFibGUkUGFja2FnZSwgaW5mbyRvdGhlclBrZ3MkZmxleHRhYmxlJFZlcnNpb24sCiAgaW5mbyRvdGhlclBrZ3MkZ2dwbG90MiRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkZ2dwbG90MiRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJHBsb3RseSRQYWNrYWdlLCAgICBpbmZvJG90aGVyUGtncyRwbG90bHkkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyRyZWFkciRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkcmVhZHIkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyRyZWFkeGwkUGFja2FnZSwgICAgIGluZm8kb3RoZXJQa2dzJHJlYWR4bCRWZXJzaW9uLAogIGluZm8kb3RoZXJQa2dzJHRpYmJsZSRQYWNrYWdlLCAgICBpbmZvJG90aGVyUGtncyR0aWJibGUkVmVyc2lvbiwKICBpbmZvJG90aGVyUGtncyR0aWR5ciRQYWNrYWdlLCAgICAgaW5mbyRvdGhlclBrZ3MkdGlkeXIkVmVyc2lvbgopIHw+IAogIHFmbGV4dGFibGUoKSB8PiAKICBzZXRfY2FwdGlvbigKICAgICJUYWJlbGEgeHggLSBjb25maWd1cmHDp8OjbyBkZSBwYWNvdGVzIG5lY2Vzc8OhcmlvcyBlIHJlc3BlY3RpdmFzIHZlcnPDtWVzIG3DrW5pbWFzIHF1ZSBkZXZlbSBzZXIgdXRpbGl6YWRhcyBwYXJhIHJlcHJvZHV6aXIgb3MgY8OzZGlnb3MiCiAgKQpgYGAKCgojIyAqKkN1aWRhZG9zIGNvbSBhIHBsYW5pbGhhIC54bHN4IHF1ZSBzZXLDoSBpbXBvcnRhZGEgKHBhcmEgcXVlIG1hbnRlbmhhIG8gcGFkcsOjbyBkYSBwbGFuaWxoYSBkZSByZWZlcsOqbmNpYSBkbyBJQ01CaW8pKiogCgpBbGd1bWFzIGZ1bsOnw7VlcyBmb3JhbSBlc2NyaXRhcyBwYXJhIGZ1bmNpb25hciB0b21hbmRvIGNvbW8gYmFzZSBkZSBkYWRvcyBkZSByZWZlcsOqbmNpYSBhIHBsYW5pbGhhIGVtIGZvcm1hdG8gZXhjZWwgYFBsYW5pbGhhIE9maWNpYWwgY29uc29saWRhZGEgZGUgTWFzdG8tYXZlcyAyMDE0LTIxIFZhbGlkYWRhIENFTUFWRSBDUEIgQ0VOQVAueGxzeGAgZGlzcG9uaWJpbGl6YWRhIHBlbG8gUHJvamV0byBNb25pdG9yYS4gRXN0YXMgZnVuw6fDtWVzIGNhcnJlZ2FtIG9zIGRhZG9zIGUgZmF6ZW0gdW1hIHPDqXJpZSBkZSB0cmFuc2Zvcm1hw6fDtWVzIHBhcmEgZGV2b2x2ZS1sb3Mgbm8gZm9ybWF0byBwYWRyb25pemFkbyBkbyBwcm9ncmFtYSBESVNUQU5DRSBwYXJhIFdpbmRvd3MuIFBvcnRhbnRvLCBwYXJhIGdhcmFudGlyIGEgcmVwcm9kdXRpYmlsaWRhZGUgZG9zIGPDs2RpZ29zIHByb2R1emlkb3MgZW0gdmVyc8O1ZXMgYXR1YWxpemFkYXMgZGEgYmFzZSBkZSBkYWRvcyBkbyBNb25pdG9yYSwgw6kgaW1wb3J0YW50ZSB0b21hciBhbGd1bnMgY3VpZGFkb3MuIAoKTyBwcmltZWlybyBlIG1haXMgaW1wb3J0YW50ZSBjdWlkYWRvIMOpIG1hbnRlciBvcyBtZXNtb3Mgbm9tZXMgZGFzIGNvbHVuYXMgZW0gdmVyc8O1ZXMgYXR1YWxpemFkYXMgZGEgYmFzZSBkZSBkYWRvcyBkbyBNb25pdG9yYS4gQXMgcHJpbWVpcmFzIGZ1bsOnw7VlcywgYWzDqW0gZGUgY2FycmVnYXIgb3MgZGFkb3MsIGFwbGljYW0gdW1hIHPDqXJpZSBkZSB0cmFuc2Zvcm1hw6fDtWVzLiBPcyBub21lcyBkYXMgY29sdW5hcyBzw6NvIGFsdGVyYWRvcywgZSBhIGVzc2FzIHPDo28gYXRyaWJ1w61kb3MgdGlwb3MgKGRhdGEsIGNhcmFjdGVyLCBmYXRvciAsIGludGVpcm8gZSBudW3DqXJpY28pLCBsaW5oYXMgc8OjbyBlbGltaW5hZGFzIGUgbm92YXMgY29sdW5hcyBzw6NvIGdlcmVhZGFzLiBQYXJhIGV4ZW1wbGlmaWNhciwgdmVqYSBvIGPDs2RpZ28gYWJhaXhvLiBFbGUgZm9pIGVzY3JpdG8gcGFyYSBleGVjdXRhciBhcyBwcmltZWlyYXMgdHJhbnNmb3JtYcOnw7VlcyBub3MgZGFkb3MgZSBjb25zdGl0dWkgbyBjb3JwbyBkYSBmdW7Dp8OjbyBgY2FycmVnYXJfZGFkb3NfZmlsdHJhZG9zKClgLiAKCmBgYHtyfQojIGNhcnJlZ2FyIGEgYmFzZSBkZSBkYWRvcyBkbyBNb25pdG9yYQpkYWRvc19icnV0b3MgPC0gY2FycmVnYXJfZGFkb3NfYnJ1dG9zX3hsc3goKQoKIyBnZXJhciBvIGRhdGEuZnJhbWUgZGVzZWphZG8KZGFkb3NfY29tcGxldG9zIDwtIGRhZG9zX2JydXRvcyB8PiAgCiAgIyBzZWxlY2lvbmFyIGFzIGNvbHVuYXMgbmVjZXNzw6FyaWFzIHBhcmEgYXMgYW5hbGlzZXMsIHBhZHJvbml6YW5kbyBvcyBub21lcyBwYXJhIG8gZm9ybWF0byBESVNUQU5DRQogIGRwbHlyOjpzZWxlY3QoCiAgICB1Y19jb2RlID0gQ0RVQywKICAgIHVjX25hbWUgPSBgTG9jYWwgLSBOb21lIGRhIFVuaWRhZGUgZGUgQ29uc2VydmHDp8Ojb2AsCiAgICBlYV9udW1iZXIgPSBgTsO6bWVybyBkYSBFc3Rhw6fDo28gQW1vc3RyYWxgLAogICAgZWFfbmFtZSA9IGBOb21lIGRhIEVBYCwKICAgIHNlYXNvbiA9IGBFc3Rhw6fDo28gZG8gYW5vYCwKICAgIHNhbXBsaW5nX2RheSA9IGBkYXRhIGRhIGFtb3N0cmFnZW1gLAogICAgZGF5X2VmZm9ydCA9IGBFc2ZvcsOnbyBkZSBhbW9zdHJhZ2VtIHRhbWFuaG8gZGEgdHJpbGhhIChtKWAsCiAgICBzcCA9IGBFc3DDqWNpZXMgdmFsaWRhZGFzIHBhcmEgYW7DoWxpc2UgZG8gSUNNQmlvYCwKICAgIGRpc3RhbmNlID0gYGRpc3TDom5jaWEgKG0pICAgICBkbyBhbmltYWwgZW0gcmVsYcOnw6NvIGEgdHJpbGhhYCwKICAgIGdyb3VwX3NpemUgPSBgbsKwIGRlIGFuaW1haXNgLAogICAgb2JzZXJ2YWRvcmVzID0gYG5vbWUgZG9zIG9ic2VydmFkb3Jlc2AKICApIHw+CiAgIyBhdHJpYnVpciBvcyB0aXBvcyBjb3JyZXRvcyDDoHMgY29sdW5hcyBlIGNyaWFyIG5vdmFzIGNvbHVuYXMKICAgIGRwbHlyOjptdXRhdGUoCiAgICAgIHVjX2NhdGVnb3J5ID0gc3RyaW5naTo6c3RyaV9leHRyYWN0X2ZpcnN0X3dvcmRzKAogICAgICB1Y19uYW1lCiAgICApLAogICAgIyBhYnJldmlhIG8gbm9tZSBkYXMgVUNzCiAgICB1Y19uYW1lX2FidiA9IGZvcmNhdHM6Omx2bHNfcmV2YWx1ZSgKICAgICAgdWNfbmFtZSwKICAgICAgbmV3X2xldmVscyA9IGMoCiAgICAgICAgIkVUTSIsICJFTSIsICJFTiIsICJFU0dUIiwgIkZKIiwgIlBDViIsICJQQSIsICJQU0JvYyIsICJQU0JvZCIsICJQU0MiLAogICAgICAgICJQU00iLCAiUFNDIiwgIlBTRCIsICJQU1AiLCAiUFNPIiwgIlBQTiIsICJQQ08iLCAiUEkiLCAiUEphw7oiLCAiUEp1ciIsCiAgICAgICAgIlBNUiIsICJQUyIsICJQViIsICJQQ0EiLCAiUE1UIiwgIlJHIiwgIlJKIiwgIlJUYXAiLCAiUlUiLCAiUkciLAogICAgICAgICJSVHJvbSIsICJSQVQiLCAiUkJBIiwgIlJDSSIsICJSQ00iLCAiUlJDIiwgIlJST1AiLCAiUklBIiwgIlJSQSIsICJSVEEiCiAgICAgICkKICAgICksCiAgICAgICMgYXRyaWJ1aXIgbyB0aXBvIGRhdGEgw6AgY29sdW5hIHNhbXBsaW5nX2RheQogICAgICB5ZWFyID0gbHVicmlkYXRlOjp5ZWFyKAogICAgICAgIHNhbXBsaW5nX2RheQogICAgICApLAogICAgICAjIGF0cmlidWlyIG8gdGlwbyBmYXRvciDDoHMgY29sdW5hcyBkbyB0aXBvIGNhcmFjdGVyCiAgICAgIGFjcm9zcygKICAgICAgICB3aGVyZSgKICAgICAgICAgIGlzLmNoYXJhY3RlcgogICAgICAgICksCiAgICAgICAgYXMuZmFjdG9yCiAgICAgICksCiAgICAgICMgc3Vic3RpdHVpciBzZXBhcmFkb3JlcyBkZSBub21lIHBvciAiLCIKICAgICAgbm92byA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKICAgICAgICBvYnNlcnZhZG9yZXMsIAogICAgICAgICIgZSAiLAogICAgICAgICIsICIKICAgICAgKSwKICAgICAgIyBzdWJzdGl0dWlyIHNlcGFyYWRvcmVzIGRlIG5vbWUgcG9yICIsIgogICAgICBub3ZvID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAogICAgICAgIG5vdm8sIAogICAgICAgICIgRSAiLAogICAgICAgICIsICIKICAgICAgKSwKICAgICAgIyBzdWJzdGl0dWlyIHNlcGFyYWRvcmVzIGRlIG5vbWUgcG9yICIsIgogICAgICBub3ZvID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKAogICAgICAgIG5vdm8sIAogICAgICAgICIvIiwKICAgICAgICAiLCAiCiAgICAgICksCiAgICAgICMgc3Vic3RpdHVpciBzZXBhcmFkb3JlcyBkZSBub21lIHBvciAiLCIKICAgICAgbm92byA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgKICAgICAgICBub3ZvLCAKICAgICAgICAiOyIsCiAgICAgICAgIiwgIgogICAgICApLAogICAgICAjIHN1YnN0aXR1aXIgc2VwYXJhZG9yZXMgZGUgbm9tZSBwb3IgIiwiCiAgICAgIG5vdm8gPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoCiAgICAgICAgbm92bywgCiAgICAgICAgIiBhICIsCiAgICAgICAgIiwgIgogICAgICApIAogICAgKSB8PgogICMgdHJhbnNmb3JtYXIgb3Mgbm9tZXMgZG9zIG9ic2VydmFkb3JlcyBkYSBjb2x1bmEgbm92byBlbSBjb2x1bmFzIGluZGl2aWR1YWlzCnRpZHlyOjpzZXBhcmF0ZV93aWRlcl9kZWxpbSgKICBub3ZvLCAKICAiLCIsCiAgbmFtZXMgPSBjKAogICAgIm9iczEiLCAib2JzMiIsICJvYnMzIiwgIm9iczQiLCAib2JzNSIsICJvYnM2IgogICksCiAgdG9vX2ZldyA9ICJhbGlnbl9zdGFydCIKKSB8PiAKICAjIGdlcmFyIHVtYSBub3ZhIGNvbHVuYSBudW1iZXJfb2JzZXJ2ZXJzIGNvbSBvIG7Dum1lcm8gdG90YWwgZGUgb2JzZXJ2YWRvcmVzIGVtIHVtIG1lc21vIHRyYW5zZWN0bwogIGRwbHlyOjptdXRhdGUoCiAgICAjIHNlIG8gdmFsb3IgZGEgb2JzZXJ2YcOnw6NvIMOpIGRpZmVyZW50ZSBkZSBOQSwgc3Vic3RpdHVpciBwb3IgMSwgc2UgZm9yIE5BLCBzdWJzdGl0dWlyIHBvciAwCiAgICBvYnMxID0gaWZlbHNlKCFpcy5uYShvYnMxKSwgMSwgMCksCiAgICBvYnMyID0gaWZlbHNlKCFpcy5uYShvYnMyKSwgMSwgMCksCiAgICBvYnMzID0gaWZlbHNlKCFpcy5uYShvYnMzKSwgMSwgMCksCiAgICBvYnM0ID0gaWZlbHNlKCFpcy5uYShvYnM0KSwgMSwgMCksCiAgICBvYnM1ID0gaWZlbHNlKCFpcy5uYShvYnM1KSwgMSwgMCksCiAgICBvYnM2ID0gaWZlbHNlKCFpcy5uYShvYnM2KSwgMSwgMCksCiAgICAjIGdlcmEgbm92YSBjb2x1bmEgbnVtYmVyX29ic2VydmVycyBhIHBhcnRpciBkYSBzb21hIGRhcyBjb2x1bmFzIGRlIG9ic2VydmFkb3JlcyBpbmRpdmlkdWFpcwogICAgbnVtYmVyX29ic2VydmVycyA9IG9iczEgKyBvYnMyICsgb2JzMyArIG9iczQgKyBvYnM1ICsgb2JzNgogICkgfD4gCiAgIyBhZ3J1cGFyIG9zIGRhZG9zIHBlbGFzIGNvbHVuYXMgZWFfbmFtZSBlIHNhbXBsaW5nX2RheQogIGdyb3VwX2J5KAogICAgZWFfbmFtZSwgCiAgICBzYW1wbGluZ19kYXkKICApIHw+IAogICMgYW5pbmhhciBhcyBvYnNlcnZhw6fDtWVzIGFncnVwYWRhcyB1ZW0gbGlzdGFzCiAgbmVzdCgpIHw+IAogICMgY29tcGxldGFyIGNvbSBvIHZhbG9yIGNvcnJldG8gYXMgbGluaGFzIHZhemlhcyBkYXMgZGEgdmFyacOhdmVsIGRheV9lZmZvcnQKICBtdXRhdGUoCiAgICBkYXlfZWZmb3J0MiA9IHB1cnJyOjptYXAoCiAgICAgIGRhdGEsIFwoLngpIHJlcCgKICAgICAgICAueCRkYXlfZWZmb3J0WwogICAgICAgICAgIWlzLm5hKAogICAgICAgICAgICAueCRkYXlfZWZmb3J0CiAgICAgICAgICApCiAgICAgICAgXVsxXQogICAgICApCiAgICApCiAgKSB8PiAKICAjIGRlc2FuaWhhciBvcyBkYWRvcwogIHVubmVzdCgKICAgIGMoCiAgICAgIGRhdGEsIAogICAgICBkYXlfZWZmb3J0MgogICAgKQogICkgfD4gCiAgIyBkZXNhZ3J1cGFyIG9zIGRhZG9zCiAgdW5ncm91cCgpIHw+IAogICMgc2VsZWNpb25hciBhcyBjb2x1bmFzIGRlc2VqYWRhcyBlIGV4Y2x1aXIgYXMgaW5kZXNlamFkYXMKICBzZWxlY3QoCiAgICB0aWR5c2VsZWN0OjpzdGFydHNfd2l0aChjKCJ1YyIsICJlYSIpKSwKICAgIHNlYXNvbiwKICAgIHllYXIsCiAgICBzYW1wbGluZ19kYXksCiAgICBkYXlfZWZmb3J0ID0gZGF5X2VmZm9ydDIsCiAgICBzcDpudW1iZXJfb2JzZXJ2ZXJzLAogICAgLWRheV9lZmZvcnQsCiAgICAtdGlkeXNlbGVjdDo6c3RhcnRzX3dpdGgoIm9icyIpCiAgKSB8PgogICMgZmlsdHJhciBvcyBkYWRvcyBwZWxhIFVDIGUgZXNww6ljaWUgZGVzZWphZGFzCiAgICBkcGx5cjo6ZmlsdGVyKAogICAgICB1Y19uYW1lID09ICJSZXNleCBUYXBhasOzcy1BcmFwaXVucyIsCiAgICAgIHNwID09ICJEYXN5cHJvY3RhIGNyb2Nvbm90YSIKICAgICkgfD4gCiAgcmVsb2NhdGUoCiAgICB1Y19jYXRlZ29yeSwKICAgIC5iZWZvcmUgPSB1Y19uYW1lCiAgKSB8PiAKICByZWxvY2F0ZSgKICAgIHVjX25hbWVfYWJ2LAogICAgLmFmdGVyID0gdWNfbmFtZQogICkKCmRhZG9zX2NvbXBsZXRvcwpgYGAKCmBgYHtyfQojIGdlcmFyIHRhYmVsYSBkaW7Dom1pY2EgZG9zIGRhZG9zIGNvbXBsZXRvcwpkYWRvc19jb21wbGV0b3MgfD4gCiAgc2xpY2UoCiAgICAxOjEwMDAKICApIHw+IAogIGRhdGF0YWJsZSgKICAgIGZpbHRlciA9IGxpc3QoCiAgICAgIHBvc2l0aW9uID0gInRvcCIKICAgICkKICApCmBgYAoKTyB0cmVjaG8gZG8gY8OzZGlnbyBxdWUgdmFpIGRhIGxpbmhhIDEwMSBhIDExMyBzZXJ2ZSBzZWxlY2lvbmFyIGFwZW5hcyBhcyBjb2x1bmFzIGRlIGludGVyZXNzZSBwcmVzZW50ZSBub3MgZGFkb3Mgb3JpZ2luYWlzLiBOb3RlIHF1ZSBvcyBub21lcyBkYXMgcGxhbmlsaGFzIG9yaWdpbmFpcyBjb25zdGFtIG5lc3NlIHRyZWNoby4gQ2FzbyBvIG5vbWUgZGUgcXVhbHF1ZSB1bWEgZGVzc2FzIGNvbHVuYXMgc2VqYSBhbHRlcmFkbyBhIGZ1bsOnw6NvIGRlaXhhcsOhIGRlIGZ1bmNpb25hci4KCk91dHJvIGFzcGVjdG8gaW1wb3J0YW50ZSDDqSBhIHByZXNlbsOnYSBkZSBvYnNlcnZhw6fDtWVzIG7Do28gcHJlZW5jaGlkYXMgKGV4LiBjw6lsdWxhcyB2YXppYXMpIG5vcyBkYWRvcyBvcmlnaW5haXMuIEEgZnVuw6fDo28gZm9pIGRlc2VuaGEgcGFyYSByZXNvbHZlciBhbGd1bnMgcHJvYmxlbWFzIHByZXNlbnRlcyBub3MgZGFkb3Mgb3JpZ2luYWlzLiBQb3IgZXhlbXBsbywgbmFzIG8gdHJlY2hvIGRvIGPDs2RpZ28gZGFzIGxpbmhhcyB4eCBhIHh4IGFzIG9ic2VydmHDp8O1ZXMgdmF6aWFzIChgTkFgcykgc8OjbyBzdWJzdGl0dWlkYXMgcGVsbyB2YWxvciBjb3JyZXRvIG5hIGNvbHVuYSBgZGF5X2VmZm9ydGAuIEVzc2EgY29ycmXDp8OjbyBjb250aW5udWFyw6Egc2VuZG8gcmVhbGl6YWRhIGVtIHZlcnPDtWVzIGF0dWFsaXphZGFzIGRvcyBkYWRvcyBkbyBNb25pdG9yYS4gUG9yw6ltLCBzZSBvdXRyYXMgY29sdW5hcyBhbMOpbSBkYXMgcXVlIGVzdMOjbyBzZW5kbyBjb3JyaWdpZGFzIHBvc3N1aXJlbSBvYnNlcnZhw6fDtWVzIHZhemlhcyBvcyBkYWRvcyBzZXLDo28gY2FycmVnYWRvcyBlIHRyYW5zZm9ybWFkb3MsIHBvcsOpbSBvdXRyYXMgZnVuw6fDtWVzIHBvZGVtIHRlciBvIHNldSBmdW5jaW9uYW1lbnRvIGNvbXByb21ldGlkby4gUG9yIGV4ZW1wbG8uLi4gKGZ1bsOnw7VlcyBkZSB2aXN1YWxpemHDp8OjbyBlIGRvIHBhY290ZSBkaXN0YW5jZSBxdWUgcG9kZW0gbmHDtSBmdW5jaW9uYXIgZGV2aWRvIGEgYXVzw6puY2lhIGRlIG9ic2VydmHDp8OjbykKCkRlbnRyZSB0b2RhcyBhcyBmdW7Dp8O1ZXMgZGUgY2FycmVnYW1lbnRvIGRlIGRhZG9zLCBhcGVuYXMgYGNhcnJlZ2FyX2RhZG9zX2JydXRvcygpYCBjYXJyZWdhIGEgYmFzZSBkZSBkYWRvcyBvcmlnaW5haXMgZG8gTW9uaXRvcmEsIGRpcmV0YW1lbnRlIGRvIGRpcmV0w7NyaW8gYGRhdGEtcmF3L21vbml0b3JhX21hc3RvX2F2ZXNfMjAyM18wNF8wNC54bHN4YC4gQW8gbWVzbW8gdGVtcG8gcXVlIGNhcnJlZ2EgZSB0cmFuc2Zvcm1hIG9zIGRhZG9zLCBlc3NhIGZ1bsOnw6NvIGdlcmEgdW1hIHZlcnPDo28gZW0gdW0gZm9ybWF0byBtYWlzIGxldmUsIGAucmRzYCwgbm8gZGlyZXTDs3JpbyBgZGF0YS1yYXdgIChgZGF0YS1yYXcvbW9uaXRvcmFfbWFzdG9fYXZlc18yMDIzXzA0XzA0LnJkc2ApLiBBIGZ1bsOnw6NvIHNlZ3VpbnRlIG5vIGZsdXhvIGRlIHRyYWJhbGhvIGNhcnJlZ2EgYSBiYXNlIGEgcGFydGlyIGRlc3NhIHZlcnPDo28gbWFpcyBsZXZlLiBMb2dvLCBzZW1wcmUgcXVlIGhvdXZlciBhdHVhbGl6YcOnw7VlcyBubyBhcnF1aXZvIG9yaWdpbmFsIGRlIGRhZG9zIGJydXRvcyDDqSBuZWNlc3PDoXJpbyBpbmljaWFyIGEgcm90aW5hIGRlIGNhcnJlZ2FtZW50byBkZSBkYWRvcyBuZWNlc3NhcmlhbWVudGUgY29tIGEgZnVuw6fDo28gYGNhcnJlZ2FyX2RhZG9zX2JydXRvcygpYC4KCk91dHJvcyBjdWlkYWRvcy4uLgoKSW1hZ2luYW5kbyBxdWUgYSBwbGFuaWxoYSBkZSBkYWRvcyBkbyBtb25pdG9yYSDDqSBhbGdvIGRpbsOibWljbywgcXVlIG8gbm9tZSBkYXMgY29sdW5hcyBwb2RlIHNlciBlZGl0YWRvLi4uCgojIyAqKkNvbW8gYWJyaXIgb3MgYXJxdWl2b3M6IGNvbW8gc2FsdmFyIGUgZGVzY29tcGFjdGFyIGEgcGFzdGEuIEFicmlyIHByb2pldG8qKgoKVW0gcGFzc28gYSBwYXNzbyBkZSBjb21vIHNhbHZhciBhcnF1aXZvIGNvbSBvcyBjw7NkaWdvcyBlIGFicmlyLi4gUG9yIGV4ZW1wbG8sIGRhIGZvcm1hIGNvbW8gZXN0w6Egw6kgaW50ZXJlc3NhbnRlIGRlc2NvbXBhY3RhciBhIHBhc3RhIGUgYWNlc3NhciBvcyBhcnF1aXZvcyBhYnJpbmRvIG8gcHJvamV0by4gQWNobyBxdWUgaXNzbyBwb2RlIG11ZGFyLCBkZXBlbmRlbmRvIGRlIGNvbW8gdmllcm1vcyBhIGVudHJlZ2FyIG8gcHJvZHV0byBmaW5hbC4gRW50w6NvIHBvZGVtb3MgcGVuc2FyIG5lc3NhIGV4cGxpY2HDp8OjbyBubyBmaW5hbC4KCiMjICoqQ3VpZGFkb3MgY29tIGRpcmV0w7NyaW8qKgoKU2UgYSBnZW50ZSBhaW5kYSBwcmVjaXNhciB0ZXIgYWxndW0gdGlwbyBkZSBwcmVvY3VwYcOnw6NvIHF1YW50byBhIGlzc28uIEFjaG8gcXVlIG7Do28uCkV4cGxpY2FyIGEgZXN0cnR1cmEgZGUgZGlyZXTDs3Jpb3MgZG8gcHJvamV0by4KCiMjICoqQ29tbyByb2RhciBjYWRhIHRpcG8gZGUgYXJxdWl2byAobWFya2Rvd24sIHNoaW55KSoqCgpOw6NvIMOpIHRyaXZpYWwgcGFyYSBxdWVtIG7Do28gZXN0w6EgYWNvc3R1bWFkby4uLiB1c2FyIHJ1bkFwcCwga25pdC4uLiBhdMOpIG1lc21vIG8gc2hpZnQrZW50ZXIgcGFyYSByb2RhciBhcyBsaW5oYXMgZGUgY29tYW5kbyB1bWEgYSB1bWEKCiMgKipQQVJURSBJSSDigJMgQ2FycmVnYW5kbyBvcyBkYWRvcyBwYXJhIG8gUioqCgojIyAqKkRhZG9zIGJydXRvcyoqCgpOw6NvIHByZWNpc2Egc2UgYXNzdXN0YXIgY29tIGEgaW5mbmlkYWRlIGRlIGPDs2RpZ29zIG5vIGV4ZW1wbG8gYWNpbWEuIFNlcnZpdSBhcGVuYXMgcGFyYSBpbHVzdHJhciBxdWUgY29uc3RydWlyIGVzc2FzIGZ1bsOnw7VlcyBmYWNpbGl0YSBhIGV4ZWN1w6fDo28gZSBhIHJlcHJvZHV0aWJpbGlkYWRlIGRhcyBhbsOhbGlzZSBkb3MgZGFkb3MgZG8gTW9uaXRvcmEuIFBhcmEgY2FkYSB0YXJlZmEgZXhpc3RlIHVtYSBmdW7Dp8OjbyBjdWpvIGZ1bmNpb25hbWVudG8gbsOjbyBuZWNlc3NpdGEgZGUgcHJlZW5jaGltZW50byBkb3MgYXJndW1lbnRvcyAoZW1ib3JhIHNlamEgcG9zc8OtdmVsIGZvcm5lY2UtbG9zKS4gUG9yIHRyYXogZGFzIGNvcnRpbmFzLCBhcyBmdW7Dp8O1ZXMgZXhlY3V0YW0gYXMgdGFyYWZhcyBuZWNlc3PDoXJpYXMgcGFyYSBzZSBvYnRlciBvIHJlc3VsdGFkbyBkZXNlamFkby4gUG9yIGV4ZW1wbG8sIG8gbWVzbW8gcmVzdWx0YWRvIHBvZGUgc2VyIG9idGlkbyB1dGlsaXphbmRvIGFwZW5hcyBkdWFzIGZ1bsOnw7VlczogYGNhcnJlZ2FyX2RhZG9zX2JydXRvc194bHN4KClgZSBgZ2VyYXJfdGFiZGluX2RhZG9zX2JydXRvcygpYC4gCgpgYGB7cn0KIyBjYXJyZWdhciBkYWRvcyBicnV0b3MKZGFkb3NfYnJ1dG9zIDwtIGNhcnJlZ2FyX2RhZG9zX2JydXRvc194bHN4KCkKZGFkb3NfYnJ1dG9zCmBgYAoKYGBge3J9CmdlcmFyX3RhYmRpbl9kYWRvc19icnV0b3MoKQpgYGAKQSBmdW7Dp8OjbyBgZ2VyYXJfdGFiZGluX2RhZG9zX2JydXRvcygpYCwgcG9yIGNvbmZpZ3VyYcOnw6NvLCBnZXJhIHVtYSB0YWJlbGEgZGluw6JtaWNhIGNvbSAxMDAwIGxpbmhhcy4gVm9jw6ogcG9kZSBjb250cm9sYXIgbyBuw7ptZXJvIGRlIGxpbmhhcyBwZWxvIGFyZ3VtZW50byBgbl9saW5oYXMgPSBgLiBNYXMgYXRlbsOnw6NvISBFbGEgbsOjbyBmdW5jaW9uYXLDoSBjb20gdW0gbsO6bWVybyBzdXBlcmlvciBhICoqNC41MDAgbGluaGFzKiouIEFvIG11ZGFyIGEgZW50cmFkYSBkZSBkYWRvcyB1c2FuZG8gbyBhcmd1bWVudG8gYGRhZG9zID0gYCwgY2VydGlmaXF1ZS1zZSBkZSBxdWUgc2V1IG7Dum1lcm8gZGUgbGluaGFzIG7Do28gZXhjZWRhIGVzc2UgbGltaXRlIChleC4gKio0LjUwMCoqKS4gSU5TRVJJUiBOT1RBIChhcMOzcyB0ZXN0YXIgZW0gbcOhcXVpbmFzIGRpZmVyZW50ZXMpIEVzc2UgdmFsb3IgcG9kZSB2YXJpYSBkZSBhY29yZG8gY29tIGFzIGNvbmZpZ3VyYcOnw7VlcyBkYSBzdWEgbcOhcXVpbmEuCgpgYGB7cn0KZ2VyYXJfdGFiZGluX2RhZG9zX2JydXRvcygKICBuX2xpbmhhcyA9IDE6NDUwMAopCmBgYAoKIyMgKipEYWRvcyBjb21wbGV0b3MqKgoKLSB0b2RhcyBlc3DDqWNpZXMvVUNzIOKAkyBjYXJyZWdhX2RhZG9zXzEuUm1kCkRlc2NyZXZlciBvIHF1ZSBvcyBkYWRvcyB0cmF6ZW0gZSBwb3JxdWUgZm9yYW0gZm9ybWF0YWRvcyBkZXNzYSBmb3JtYS4gCgpgYGB7cn0KIyBjYXJyZWdhciBkYWRvcyBwYXJhIG8gUgpkYWRvc19jb21wbGV0b3MgPC0gY2FycmVnYXJfZGFkb3NfY29tcGxldG9zKCkgCmRhZG9zX2NvbXBsZXRvcwpgYGAKCnRhYmVsYSBkaW5hbWljYQoKYGBge3J9CiMgZ2VyYXIgdGFiZWxhIGRpbmFtaWNhIGRvcyBkYWRvcyBjb21wbGV0b3MKZ2VyYXJfdGFiZGluX2RhZG9zX2NvbXBsZXRvcygpCmBgYAoKCiMjICoqRGFkb3MgZmlsdHJhZG9zKioKCi0gcG9yIGVzcMOpY2llL1VDIOKAkyBjYXJyZWdhX2RhZG9zXzIuUm1kCmF0w6kgbyBtb21lbnRvIHVzYWRvIGNvbSBvIGV4ZW1wbG8gZGEgY3V0aWEgbmEgUmVzZXggVGFwYWrDs3MtQXJhcGl1bnMKRGVzY3JldmVyIG8gcXVlIG9zIGRhZG9zIHRyYXplbSBlIHBvcnF1ZSBmb3JhbSBmb3JtYXRhZG9zIGRlc3NhIGZvcm1hLgoKYGBge3J9CiMgY2FycmVnYXIgZGFkb3MgcGFyYSBvIFIKZGFkb3NfZmlsdHJhZG9zIDwtIGNhcnJlZ2FyX2RhZG9zX2ZpbHRyYWRvcygpCmRhZG9zX2ZpbHRyYWRvcwpgYGAKCgpgYGB7cn0KIyBnZXJhciB0YWJlbGEgZGluw6JtaWNhCmdlcmFyX3RhYmRpbl9kYWRvc19maWx0cmFkb3MoKQpgYGAKCgojICoqUGFydGUgSUlJIOKAkyBUcmFuc2Zvcm1hbmRvIGRhZG9zIHBhcmEgRGlzdGFuY2UqKgoKIyMgKipEYWRvcyBjb21wbGV0b3MqKgoKLSB0b2RhcyBlc3DDqWNpZXMvVUNzIOKAkyB0cmFuc2Zvcm1hcl9wYXJhX2Rpc3RhbmNlUi5SbWQKCmBgYHtyfQojIHRyYW5zZm9ybWFyIG9zIGRhZG9zIHBhcmEgbyBmb3JtYXRvIGRvIERpc3RhbmNlCmRhZG9zX2Rpc3RhbmNlUl9jb21wbGV0byA8LSB0cmFuc2Zvcm1hcl9wYXJhX2Rpc3RhbmNlUigpCmRhZG9zX2Rpc3RhbmNlUl9jb21wbGV0bwpgYGAKCmBgYHtyfQojIGdlcmFyIHRhYmVsYSBkaW5hbWljYSBkb3MgZGFkb3Mgbm8gZm9ybWF0byBkbyBkaXN0YW5jZSBkbyBSCmdlcmFyX3RhYmRpbl9kYWRvc19kaXN0YW5jZVJfY29tcGxldG8oKQpgYGAKCkVtIHByaW5jw61waW8gdHVkbyBjZXJ0byBhdMOpIGFxdWkuCgpgYGB7cn0KIyB0cmFuc2Zvcm1hciBvcyBkYWRvcyBwYXJhIG8gZm9ybWF0byBkbyBEaXN0YW5jZQpkYWRvc19kaXN0YW5jZV9yX2NvdmFyaWF2ZWlzIDwtIHRyYW5zZm9ybWFyX3BhcmFfZGlzdGFuY2VSX2NvdmFyaWF2ZWlzKCkKZGFkb3NfZGlzdGFuY2Vfcl9jb3ZhcmlhdmVpcwpgYGAKCmBgYHtyfQojIHRhYmRpbiBkZSBkYWRvc19kaXN0YW5jZVJfY292YXJpYXZlaXMKZ2VyYXJfdGFiZGluX2RhZG9zX2Rpc3RhbmNlUl9jb21wbGV0b19jb3YoKQpgYGAKCiMgKipQQVJURSBJViDigJMgRXhwbG9yYW5kbyBlIHNlbGVjaW9uYW5kbyBvcyBkYWRvcyBwYXJhIGFzIGFuw6FsaXNlcyoqCgojIyAqKlNlbGVjaW9uYW5kbyBvcyBtZWxob3JlcyBtb2RlbG9zIGRlIGVzdHVkbyBkZSBhY29yZG8gY29tIG9zIGRhZG9zKioKCkNyaXTFlWlvczoKCi0gZXNww6ljaWVzIGNvbSBtYWlvciB2b2x1bWUgZGUgZGFkb3MgdG90YWwKLSBtYWlvciB2b2x1bWUgZGUgZGFkb3MgcG9yIFVDCiDigJMgIGV4cGxvcmHDp8Ojb18wMS5uYi5odG1sIChhY2hvIHF1ZSBvIC5SbWQgcGFyYSBnZXJhciBlc3NlIGh0bWwgbsOjbyBlc3TDoSBuYSBwYXN0YSBNb25pdG9yYSkuIEV1IHRpbmhhIGdvc3RhZG8gYmFzdGFudGUgZGVzc2UgZG9jdW1lbnRvLCBjb20gYXMgdGFiZWxhcyBkaW7Dom1pY2FzLiBUYWx2ZXogZMOqIHBhcmEgc2VsZWNpb25hciBhcyBwZXJndW50YXMgcXVlIHPDo28gdsOhbGlkYXMgZGUgZGVpeGFyLyB0aXJhci8gaW5jbHVpci4KV1dGIC0gUHJvamV0byBNb25pdG9yYQotIGVzcMOpY2llcyB2YWxpZGFkYXMKLSAuLi4KCiMjIyAqKkV4cGxvcmHDp8OjbyBlIHNlbGXDp8OjbyBkZSBkYWRvcyoqCgojIyMjICoqQXNwZWN0b3MgcmVsYWNpb25hZG9zIGFvIG7Dum1lcm8gdG90YWwgZGUgb2JzZXJ2YcOnw7VlcyoqCgpTaXN0ZW1hdGl6YXIgb3MgY3JpdMOpcmlvcyB1dGlsaXphZG9zIHBhcmEgZWxpbWluYXIgb2JzZXJ2YcOnw7VlcyAobGluaGFzKS4gCgpQZW5zYXIgbnVtIGVzcXVlbWEgZGUgw6Fydm9yZSBkZSBkZWNpc8OjbyBwYXJhIHNlIGNoZWdhciBhbyBzdWJjb25qdW50byBkZSBkYWRvcyBxdWUgc2Vyw6EgYW5hbGlzYWRvcy4KCiMjIyMgKipRdWFudGFzIG9ic2VydmHDp8O1ZXMgZm9yYW0gdmFsaWRhZGFzIHBhcmEgcXVhaXMgbsOtdmVpcyB0YXhvbsO0bWljb3M/KioKCkVzc2FzIG9wZXJhw6fDtWVzIHPDo28gcmVhbGl6YWRhcyBzb2JyZSBhIHRhYmVsYSBkZSBkYWRvcyBgZGFkb3NfY29tcGxldG9zYCBwb2lzIG9zIGRhZG9zIHF1ZSBmb3JhbSB0cmFuc2Zvcm1hZG9zIHBhcmEgbyBmb3JtYXRvIGRvIGRpc3RhY2Ugbm8gUiBuw6NvIHBvc3N1ZW0gYSBjb2x1bmEgYHZhbGlkYXRpb25gLCBuZWNlc3PDoXJpYSBwYXJhIGVzc2FzIG9wZXJlYcOnw7Vlcy4gTWFpcyBhIGZyZW50ZSBvIHByb2NlZGltZW50byBkZSBjb21vIG9idGVyIG9zIGRhZG9zIHNlbGVjaW9uYWRvcyBlIHRyYW5zZm9ybWF0b3MgcGFyYSBvIGZvcm1hdG8gZGFzIGFuw6FsaXNlcyBzZXLDoSBkZW1vbnN0cmFkby4KCmBgYHtyfQojIGNvbnRhciBvYnNlcnZhw6fDtWVzIHZhbGlkYWRhcyBhbyBuw612ZWwgZGUgZXNww6ljaWUKbl9vYnNfdmFsaWRhZGFzIDwtIGNvbnRhcl9uX29ic192YWxpZGFkYXMoKQpuX29ic192YWxpZGFkYXMKYGBgCgpGb3JhbSBzZWxlY2lvbmFkYXMgYXBlbmFzIGFzIG9ic2VydmHDp8O1ZXMgdmFsaWRhZGFzIGFvIG7DrXZlbCBkZSBlc3DDqWNpZSwgc29tYW5kbyB1bSB0b3RhbCBgciBuX29ic192YWxpZGFkYXNbMV1gIG9ic2VydmHDp8O1ZXMuCgpgYGB7cn0KIyBnZXJhciBncsOhZmljbyBjb20gbsO6bWVybyBvYnNlcnZhw6fDtWVzIHZhbGlkYWRhcyBwYXJhIGNhZGEgbsOtdmVsIHRheG9uw7RtaWNvCnBsb3Rhcl9uX29ic192YWxpZGFkYXMoKQpgYGAKCkZpbG5hbG1lbnRlIGNoZWdhbW9zIGFvIHN1YmNvbmp1bnRvIGRvcyBkYWRvcyBxdWUgc2Vyw6EgdXRpbGl6YWRvIHBhcmEgc2VsZWNpb25hciBxdWFpcyBlc3DDqWNpZXMgc2Vyw6NvIGFuYWxpc2FkYXMuCgpgYGB7cn0KIyBnZXJhciB0YWJlbGEgZGUgZGFkb3Mgc2VsZWNpb25hZG9zCmRhZG9zX3NlbGVjaW9uYWRvcyA8LSBjYXJyZWdhcl9kYWRvc19zZWxlY2lvbmFkb3MoKQpkYWRvc19zZWxlY2lvbmFkb3MKYGBgCgpgYGB7cn0KIyBnZXJhciB0YWJkaW4gZGFkb3Nfc2VsZWNpb25hZG9zIApnZXJhcl90YWJkaW5fZGFkb3Nfc2VsZWNpb25hZG9zKCkKYGBgCgojIyMjICoqUXVhbnRhcyB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGFvIHRvZG8/KioKCmBgYHtyIG5fZGVfdWNzfQojIGNvbnRhciBuw7ptZXJvIHRvdGFsIGRlIFVDJ3MgCm5fdWNzIDwtIGNvbnRhcl9uX3VjKCkKbl91Y3MKYGBgCgpPcyBkYWRvcyBzw6NvIHByb3ZlbmllbnRlcyBkZSBgciBuX3Vjc2AgdW5pZGFkZXMgZGUgY29uc2VydmHDp8OjbyBhbyB0b2RvLgoKIyMjIyAqKlF1YW50YXMgZXNww6ljaWVzIGFvIHRvZG8/KioKCmBgYHtyfQpuX3NwIDwtIGNvbnRhcl9uX3NwKCkKbl9zcApgYGAKCkF0w6kgYXF1aSB0ZW1vcyBkYWRvcyBwYXJhIGByIG5fc3BgIGVzcMOpY2llcy4KCiMjIyMgKipRdWFudGFzIG9ic2VydmHDp8O1ZXMgcG9yIHVuaWRhZGUgZGUgY29uc2VydmHDp8OjbyBhbyB0b2RvPyoqCgpBcyBVQydzIGZvcmFtIGZpbHRyYWRhcyBkZSBhY29yZG8gY29tIG8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBlcm1pdGlyIGEgdmlzdWFsaXphw6fDo28uCgpBIGZ1bsOnw6NvIGRlIGNvbnRhZ2VtIGRlIFVDJ3MgZ2Vyb3UgNDAgVUMncywgbWFzIHPDsyBow6Egb2JzZXJ2YcOnw7VlcyBwYXJhIDM4LiAqTGVtYnJhciBkZSB2ZXJpZmljYXIgaXNzbyouCgpgYGB7cn0KIyBjb250YXIgbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBvciBVQwpuX29ic191YyA8LSBjb250YXJfbl9vYnNfdWMoKQpuX29ic191YwpgYGAKCipBZGljaW9uYXIgbyBub21lIGNvbXBsZXRvIGRhIFVDIG5hIGNhaXhhIGludGVyYXRpdmEgZG8gZ3LDoWZpY28qLgoqSWRlbnRpZmljYXIgb3MgcGxvdGVzIGNvbSBzdWJ0w610dWxvcyBleCB0ZW50YXIgYWRpY2lvbmFyIHTDrXR1bG8gYW9zIHBsb3RlcyoKKipBZGljaW9uYXIgbm9tZXMgZGFzIFVDcyBub3MgMyBwcmltZWlyb3MgZ8OhZmljb3MgKGRlc2NvbXBhcnRpbGhhciBlaXhvIHgpKiogCgpgYGB7ciwgZmlnLmhlaWdodD0yMH0KIyBwbG90YXIgbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcG9yIFVDCnBsb3Rhcl9uX29ic191Y19pbnRlcmF0aXZvKCkKYGBgCgpgYGB7cn0KIyBnZXJhciB0YWJkaW4KZ2VyYXJfdGFiZGluX25fb2JzX3VjKCkKYGBgCgojIyMjICoqUXVhbnRhcyBvYnNlcnZhw6fDtWVzIHBhcmEgY2FkYSBlc3DDqWNpZT8qKgoKTsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBvciBlc3DDqWNpZS4KCmBgYHtyLCBmaWcuaGVpZ2h0PTIwfQojIGNvbnRhciB0b3RhbCBzcApuX29ic19zcCA8LSBjb250YXJfbl9vYnNfc3AoKQpuX29ic19zcApgYGAKCkVzc2UgZ3LDoWZpY28gcG9kZSBtZWxob3Jhci4gRGVzY29tcGFydGlsaGFyIG8gZWl4byB4PyBBYnJldmlhciBvIG5vbWUgZGFzIGVzcMOpY2llcy4uLgoKYGBge3IsIGZpZy5oZWlnaHQ9MjB9CiMgcGxvdGFyIG8gbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcG9yIFVDCnBsb3Rhcl9uX3NwX3VjX2ludGVyYXRpdm8oKQpgYGAKClRhYmVsYSBpbnRlcmF0aXZhIHBhcmEgY29uc3VsdGEgZG8gbsO6bWVybyBkZSBvYnNlcnZhw6fDtWVzIHBvciBlc3DDqWNpZS4KYGBge3J9CiMgZ2VyYXIgdGFiZWxhIGRpbsOibWljYSBjb20gbyBuw7ptZXJvIHRvdGFsIGRlIG9ic2V2YcOnw7VlcyBwb3IgZXNww6ljaWUKZ2VyYXJfdGFiZGluX25fb2JzX3NwKCkKYGBgCgojIyMjICoqUXVhaXMgZSBxdWFudGFzIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llIHBvciB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvPyoqCgpHZXJhciBmdW7Dp8OjbyBwYXJhIHBsb3RhciBvIG7Dum1lcm8gZGUgb2JzZXJ2YcOnw7VlcyBwYXJhIGNhZGEgZXNww6ljaWUgcG9yIFVDLgoKYGBge3IsIGZpZy5oZWlnaHQ9MjB9CgpgYGAKCmBgYHtyfQojIGdlcmFyIHRhYmVsYSBjb20gbyBuw7ptZXJvIGRlIG9ic2VydmHDp8O1ZXMgcG9yIGVzcMOpY2llIGUgcG9yIFVDCm5fb2JzX3NwX3VjIDwtIGNvbnRhcl9uX29ic19zcF91YygpCm5fb2JzX3NwX3VjCmBgYAoKR2VyYXIgZnVuw6fDo28gdGFiZWxhIGRpbsOibWljYS4KCmBgYHtyfQoKYGBgCgojIyMjICoqUXVhbnRhcyB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGZvcmFtIGFtb3N0cmFkYXMgZW0gY2FkYSBhbm8/KioKCkdlcmFyIGZ1bsOnw6NvIHBhcmEgdmlzdWFsaXphciBuw7ptZXJvIGRlIFVDcyBhbW9zdHJhZGFzIGVtIGNhZGEgYW5vLgoKYGBge3J9CgpgYGAKCgpgYGB7ciwgZWNobz1GQUxTRX0KIyBnZXJhciB0YWJlbGEgY29tIG8gbsO6bWVybyBkZSB1bmlkYWRlcyBkZSBjb25zZXJ2YcOnw6NvIGFtb3N0cmFkYXMgZW0gY2FkYSBhbm8Kbl91Y3NfYW5vIDwtIGNvbnRhcl9uX3VjX2FubygpCm5fdWNzX2FubwpgYGAKCkdlcmFyIGZ1bsOnw6NvIHBhcmEgdGFiZWxhIGRpbsOibWljYS4KCmBgYHtyfQoKYGBgCgojIyMjICoqUXVhaXMgdW5pZGFkZXMgZGUgY29uc2VydmHDp8OjbyBmb3JhbSBhbW9zdHJhZGFzIGVtIHVtIG1haW9yIG7Dum1lcm8gZGUgYW5vcz8qKgoKR2VyYXIgZ3LDoWZpY28gY29tIG8gbsO6bWVybyBkZSBhbm9zIGVtIHF1ZSBjYWRhIFVDIGZvaSBhbW9zdHJhZGEuCgpgYGB7cn0KCmBgYAoKVGFiZWxhCgpgYGB7cn0Kbl9hbm9fdWMgPC0gY29udGFyX25fYW5vX3VjKCkKbl9hbm9fdWMgIApgYGAKCkdlcmFyIHRhYmVsYSBkaW5hbWljYS4KCmBgYHtyfQoKYGBgCgoKIyMjIyAqKlF1YW50YXMgb2JzZXJ2YcOnw7VlcyBmb3JhbSByZWFsaXphZGFzIHBvciBVQyBlbSBjYWRhIGFubz8qKgoKVGFiZWxhIGludGVyYXRpdmEgcGFyYSBjb25zdWx0YXIgcXVhbnRhcyBvYnNlcnZhw6fDtWVzIGZvcmFtIHJlYWxpemFkYXMgcG9yIGFubyBlbSBjYWRhIFVDCmBgYHtyfQpkYWRvczEgfD4gIAogIGRwbHlyOjpjb3VudChhbm8sIHVjcykgfD4gCiAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIpKQpgYGAKCiMjIyMgKipRdWFudGFzIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llcyBwb3IgYW5vPyoqCgpUYWJlbGEgaW50ZXJhdGl2YSBwYXJhIGNvbnN1bHRhciBxdWFudGFzIG9ic2VydmHDp8O1ZXMgZm9yYW0gcmVhbGl6YWRhcyBwYXJhIGNhZGEgZXNww6ljaWUgZW0gY2FkYSBhbm8KYGBge3J9CmRhZG9zMSB8PiAgCiAgZHBseXI6OmNvdW50KGFubywgZXNwZWNpZSkgfD4gCiAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIpKQpgYGAKCiMjIyMgKipRdWFudGFzIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llcyBwb3IgVUMgZSBwb3IgYW5vPyoqCgpUYWJlbGEgaW50ZXJhdGl2YSBwYXJhIGNvbnN1bHRhciBxdWFudGFzIG9ic2VydmHDp8O1ZXMgZm9yYW0gcmVhbGl6YWRhcyBwYXJhIGNhZGEgZXNww6ljaWUgZW0gY2FkYSBhbm8KCmBgYHtyfQpkYWRvczEgfD4gIAogIGRwbHlyOjpjb3VudChhbm8sIHVjcywgZXNwZWNpZSkgfD4gCiAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSBsaXN0KHBvc2l0aW9uID0gInRvcCIpKQpgYGAKCiMjIyMgKipRdWFudGFzIG9ic2VydmHDp8O1ZXMgcGFyYSBjYWRhIGVzcMOpY2llcyBwb3IgVUMsIHBvciBlc3Rhw6fDo28gZSBwb3IgYW5vPyoqCgpgYGB7cn0KZGFkb3MxIHw+ICAKICBkcGx5cjo6Y291bnQoYW5vLCBzZWFzb24sIHVjX25hbWUsIHNwKSB8PiAKICBEVDo6ZGF0YXRhYmxlKGZpbHRlciA9IGxpc3QocG9zaXRpb24gPSAidG9wIikpCmBgYAoKIyMjIyAqKlNlbGVjaW9uYW5kbyBtZWxob3JlcyBtb2RlbG9zIGRlIGVzdHVkbyBjb25zaWRlcmFuZG8gZXN0cmF0aWZpY2HDp8OjbyBlc3BhY2lhbC90ZW1wb3JhbCDigJMgc2UgaMOhIHN1ZmljacOqbmNpYSBhbW9zdHJhbCAoNjAtODAgb2JzZXJ2YcOnw7VlcykgcG9yIGVzdHJhdG8qKgoKLSBQb3Nzw612ZWlzIGVzdHJhdGlmaWNhw6fDtWVzIGVzcGFjaWFpcyDigJMgRUFzL1VDcwoKCQkJCQkgICAgLSBVQ3MvRXNww6ljaWVzCgoJLSBQb3Nzw612ZWlzIGVzdHJhdGlmaWNhw6fDtWVzIHRlbXBvcmFpcyDigJMgRXNww6ljaWUvVUMvQW5vIAoKIyMjIyAqKkF2YWxpYW5kbyBkaXN0w6JuY2lhIGRlIHRydW5jYW1lbnRvKioKCi0gR3LDoWZpY29zIGRlIGRpc3RyaWJ1acOnw6NvIGRhcyBmcmVxdcOqbmNpYXMgZGUgb2NvcnLDqm5jaWEgeCBkaXN0w6JuY2lhIHBlcnBlbmRpY3VsYXIuIEFycXVpdm9zIGdyw6FmaWNvLWV4cGxvcmF0b3JpbzEuUm1kIGUgZ3LDoWZpY28tZXhwbG9yYXRvcmlvMi5SbWQgKGV1IG7Do28gc2VpIGNvbW8gdm9jw6ogZmV6IHBhcmEgaW5jbHVpciBhcXVlbGEgbGluaGEgdmVybWVsaGEgY29tIG8gdmFsb3IgZGUgdyBubyBncsOhZmljbyBleHBsb3JhdMOzcmlvIDIsIG1hcyBmaWNvdSBsZWdhbCkKCiMjIyMgKipEaXN0cmlidWnDp8OjbyBkZSBkaXN0w6JuY2lhcyoqCgpgYGB7ciBkaXN0cmlidWljYW9fZHNpdGFuY2lhLCB3YXJuaW5nPUZBTFNFfQojIGNhcnJlZ2FyIGRhZG9zX2ZpbHRyYWRvcy5SIGRhIHBhc3RhIGRhdGEgcGFyYSBvIFIKZGFkb3NfZmlsdHJhZG9zIDwtIHJlYWRyOjpyZWFkX3Jkcyhjb3JyaWdpcl9kaXJldG9yaW8oY29ycmlnZSA9ICJkYXRhL2RhZG9zX2ZpbHRyYWRvcy5yZHMiKSkgCgojIGdlcmFyIG8gZ3LDoWZpY28gZXhwbG9yYXTDs3JpbyBkYSBkaXN0cmlidWnDp8OjbyBkZSBkaXN0w6JuY2lhcyBwZXJwZW5kaWN1bGFyZXMgcGFyYSBhIGVzcMOpY2llcyBEYXN5cm9jdGEgY3JvY29ub3RhIG5hIFJlc2V4IFRhcGFqw7NzLUFyYXBpdW5zCmZpZyA8LSBkYWRvc19maWx0cmFkb3MgfD4KICAjIGV4Y2x1aXIgTkEncyBkYSB2YXJpw6F2ZWwgZGlzdGFuY2UKICB0aWR5cjo6ZHJvcF9uYShkaXN0YW5jZSkgfD4gCiAgZ3JhZmljb19leHBsb3JhdG9yaW8zKCkKCmZpZwpgYGAKCiMjIyMgKipBdmFsaWFuZG8gY292YXJpw6F2ZWlzKioKCuKAkyBBcyBjb3ZhcmnDoXZlaXMgZGV2ZW0gc2VyIHBlbnNhZGFzIGRlIGFjb3JkbyBjb20gbyBncnVwbyB0YXhvbsO0bWljby4gRXNww6ljaWVzIHF1ZSBmb3JtYW0gZ3J1cG9zIGRldmVtIHRlciBhIGNvdmFyacOhdmVsIOKAmHNpemXigJkuIAoKQXMgZXN0cmF0w6lnaWFzIGRlIGVzdHJhdGlmaWNhw6fDo28gcG9kZW0gc2VyIHN1YnN0aXR1w61kYXMgcG9yIGNvdmFyacOhdmVpcyB0YW1iw6ltIChlc3RyYXRvcyBlc3BhY2lhaXMvIGFubykKCkNvbW8gY292YXJpw6F2ZWwgdGVtcG9yYWwsIHBvZGUgc2UgcGVuc2FyIGVtIHVzYXIsIGFsw6ltIGRvIGFubywgYSBlc3Rhw6fDo28gZG8gYW5vIChzZWFzb24pLCBvIGhvcsOhcmlvIGRvIGRpYSAocGFyYSBhbmltYWlzIHF1ZSB2YXJpYW0gYSBhdGl2aWRhZGUpLiBPIGhvcsOhcmlvIGRvIGRpYSBwb2RlIHNlciBjb252ZXJ0aWRvIGVtIHRlbXBvIGFww7NzIG5hc2NlciBkbyBzb2wgKGNvbW8gbm8gZXhlbXBsbykuIE1hcyBwYXJhIGlzc28gw6kgbmVjZXNzw6FyaW8gY3JpYXIgZXNzYSB2YXJpw6F2ZWwgbm8gZGF0YXNldC4gRSBuw6NvIMOpIHRyaXZpYWwgcG9ycXVlIHByZWNpc2Egc2FiZXIgbyBob3LDoXJpbyBkZSBuYXNjZXIgZG8gc29sIGVtIGNhZGEgZGlhL2xvY2FsIHBhcmEgY2FsY3VsYXIuCgoqKkFURU7Dh8ODTzogZ2VyYXIgZ3LDoWZpY29zIGRpc3TDom5jaWEgeCBjb3ZhcmnDoXZlbCoqCgpFeGVtcGxvIGRlIEdyw6FmaWNvcyBkZSBNYXJxdWVzIGV0IGFsLiAyMDA3CgojICoqUEFSVEUgViDigJMgQWp1c3RhbmRvIG9zIG1vZGVsb3MqKgoKRXNzZSB0cmFiYWxobyBkbyBNYXJxdWUgZXQgYWwuIDIwMDcgw6kgdW1hIGJvYSByZWZlcsOqbmNpYSBkZSBjb21vIHVzYXIgYXMgYWJvcmRhZ2VucyBDRFMgZ2xvYmFsLCBDRFMgZXN0cmF0aWZpY2FkYSBlIE1DRFMuCgpBcXVpLCDDqSBwb3Nzw612ZWwgdGVzdGFyIGFsZ3VucyBjYW1pbmhvcyBkZSBtb2RlbG9zLiBBIGVzdHJhdGlmaWNhw6fDo28gc8OzIGZheiBzZW50aWRvIHF1YW5kbyBvIHZvbHVtZSBkZSBkYWRvcyBmb3IgZ3JhbmRlLiBBaW5kYSBhc3NpbSBvIHVzbyBkZSBjb3ZhcmnDoXZlaXMgcG9kZSBzdWJzdGl0dWlyIGEgZXN0cmF0aWZpY2HDp8Ojby4gUGVuc2FyIGVtIGNvbW8gb3JpZW50YXIgbyB1c28gZGVzc2FzIGFib3JkYWdlbnMKCiMjICoqTW9kZWxvcyBwZWxhIGFib3JkYWdlbSBDRFMg4oCTIGRhZG9zIGdsb2JhaXMqKgoKLSBmdW7Dp8OjbyBkcyBkbyBEaXN0YW5jZSAoYXJndW1lbnRvcyBiw6FzaWNvczogdHJ1bmNhdGlvbjsga2V5LCBhZGp1c3RtZW50LCBzY2FsZS4uLiBlc3R1ZGFyIGFyZ3VtZW50b3MgcGFyYSB2ZXIgc2UgbWFpcyBhbGd1bSBpbnRlcmVzc2EpCgojIyAqKk1vZGVsb3MgcGVsYSBhYm9yZGFnZW0gQ0RTIOKAkyBkYWRvcyBlc3RyYXRpZmljYWRvcyoqCgotIEFxdWkgcHJlY2lzYSB2ZXIgZGlyZWl0aW5obyBvcyBjdWlkYWRvcyBxdWUgcHJlY2lzYSB0ZXIgcGFyYSBhanVzdGFyIGFzIGZ1bsOnw7VlcyBub3MgZGFkb3MgZXN0cmF0aWZpY2Fkb3MuIEFjaG8gcXVlIGZheiBlbSBibG9jb3MuIFZhaSBhcGxpY2FuZG8gb3MgbWVzbW9zIHBhcsOibWV0cm9zIHBhcmEgdG9kb3Mgb3MgZXN0cmF0b3MgYSBjYWRhIG1vZGVsby4KCi0gcGFyYSBjYWRhIGVzdHJhdG8gKGVzcGFjaWFsIG91IHRlbXBvcmFsKSB1c2FyIC0gZnVuw6fDo28gZHMgZG8gRGlzdGFuY2UgKGFyZ3VtZW50b3MgYsOhc2ljb3M6IHRydW5jYXRpb247IGtleSwgYWRqdXN0bWVudCwgc2NhbGUuLi4gZXN0dWRhciBhcmd1bWVudG9zIHBhcmEgdmVyIHNlIG1haXMgYWxndW0gaW50ZXJlc3NhKQoKIyMgKipNb2RlbG9zIHBlbGEgYWJvcmRhZ2VtIE1DRFMg4oCTIGRhZG9zIGdsb2JhaXMqKgoKQXF1aSBuw6NvIGZheiBzZW50aWRvIGVzdHJhdGlmaWNhcgoKLSBmdW7Dp8OjbyBkcyBkbyBEaXN0YW5jZSAoYXJndW1lbnRvcyBiw6FzaWNvczogdHJ1bmNhdGlvbjsga2V5LCBhZGp1c3RtZW50LCBzY2FsZS4uLiBlc3R1ZGFyIGFyZ3VtZW50b3MgcGFyYSB2ZXIgc2UgbWFpcyBhbGd1bSBpbnRlcmVzc2EuLi4gcGFyYSBhcyBjb3ZhcmnDoXZlaXMgZW50cmEgbyBhcmd1bWVudG8gZm9ybXVsYSkKCkRpY2FzIGVtIE1pbGxlciBldCBhbC4gMjAxOSBzb2JyZSBjb3ZhcmnDoXZlaXMgKHZlciBhcnF1aXZvIG5vIGRyaXZlcikuCgojICoqUEFSVEUgVkkg4oCTIEF2YWxpYW5kbyBvcyBtb2RlbG9zKioKCiMjICoqQWp1c3RlIGRvcyBtb2RlbG9zKioKCi0gZnVuw6fDo28gZ29mX2RzIAoK4oCTIHBhcmEgZ2VyYXIgUS1RIHBsb3RzIGUgdGVzdGVzIGFzc29jaWFkb3MKCiMjICoqU2VsZWNpb25hbmRvIG1vZGVsb3MgKEFJQykqKgoK4oCTIGZ1bsOnw6NvIHN1bW1hcml6ZV9kc19tb2RlbHMKCkRJQ0FTIEVYVFJBUyBERSBNSUxMRVIgZXQgYWwuIDIwMTkKCiMgKipQQVJURSBWSUkg4oCTIFBST0RVVE8gRklOQUwqKgoKLSBDb21vIG9yZ2FuaXphcgoKLSBJbnRlcmF0aXZpZGFkZQoKKipDcmlhciBleHByZXNzw7VlcyByZWF0aXZhcyoqCgpyZWFjdGl2ZSgpCmV2ZW50UmVhY3RpdmUoKQoKb2JzZXJ2ZSgpCm9ic2VydmVFdmVudCgpCgpyZWFjdGl2ZVZhbCgpCnJlYWN0aXZlVmFsdWVzKCkKCmlzb2xhdGUoKQoKCi0gZ2VyYXIgbyB0YWwgZG9jdW1lbnRvIGF1dG9tYXRpemFkbyBjb250ZW5kbyB0b2RvIGVzc2UgZmx1eG8gbWFpcyBvcyByZXN1bHRhZG9zIGRhcyBhbsOhbGlzZXM7CgotIHRlbnRhciB0cmFuc2Zvcm1hciBpc3NvIG51bSBkYXNoYm9hcmQvYXBsaWNhdGl2byDDum5pY28gaW50ZWdyYW5kbyBjYWRhIGV0YXBhIGRlc3NhIG51bWEgZGFzIGFiYXMgZG8gZGFzaGJvYXJkCgotIFBhY290ZSB0YXJnZXRzIHNlcmlhIMO6bHRpbD8KCiMgKipHbG9zc8OhcmlvKioKCkRlc2NyZXZlciBhcyB2YXJpw6F2ZWlzIChjb2x1bmFzKSwgdGVybW9zIHTDqWNuaWNvcyBhbyBsb25nbyBkbyB0ZXh0by4uLgoKIC0gYEVmZm9ydGAgLSBleHRlbnPDo28gdG90YWwgcGVyY29ycmlkYSBlbSBtZXRyb3Mgbm8gY29uanVudG8gZGUgZGFkb3Mgc2VsZWNpb2RvLgogCiAtIA==